#include "dirwatch.h"

#include <QTimer>
#include <QDebug>

DirWatch::DirWatch(const QString &dir, QObject *parent) :
    m_dir(dir),
    QObject(parent)
{
    m_h = CreateFile(m_dir.toStdWString().data(),
            FILE_LIST_DIRECTORY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS,
            NULL);
    if(m_h == INVALID_HANDLE_VALUE)
    {
        qCritical() << "Open " << m_dir << " failed: " << GetLastError();
    }
}

void DirWatch::watchDir()
{
    if (m_h != INVALID_HANDLE_VALUE) {
        memset(m_outBuf, 0, READ_DIR_CHANGE_BUFFER);
        if (ReadDirectoryChangesW(m_h,
                    (LPVOID)m_outBuf,
                    READ_DIR_CHANGE_BUFFER,
                    TRUE,
                    FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME,
                    &m_bytesRet,
                    NULL,
                    NULL)) {

            FILE_NOTIFY_INFORMATION *fni = (FILE_NOTIFY_INFORMATION*)m_outBuf;
            QString old_name;

            while (fni) {
                QString file_name = QString::fromStdWString(fni->FileName);
                file_name = file_name.left(fni->FileNameLength/sizeof(WCHAR));
                file_name = m_dir + "/" + file_name;
                file_name.replace("\\", "/");

                if (fni->Action==FILE_ACTION_ADDED) {
                    emit fileAdded(file_name);
                    qDebug() << "New file: " << file_name;
                } else if (fni->Action==FILE_ACTION_REMOVED) {
                    emit fileRemoved(file_name);
                    qDebug() << "Delete file: " << file_name;
                } else if (fni->Action==FILE_ACTION_RENAMED_OLD_NAME) {
                    old_name = file_name;
                    qDebug() << "Rename file (old): " << file_name;
                } else if (fni->Action==FILE_ACTION_RENAMED_NEW_NAME) {
                    emit fileRenamed(old_name, file_name);
                    qDebug() << "Rename file (new): " << file_name;
                } else {
                    qDebug() << QString("Unused action: %1, file: %2").arg(fni->Action, 8, 16, QChar('0')).arg(file_name);
                }

                //qDebug() << QString("Next entry: 0x%1").arg(fni->NextEntryOffset, 8, 16, QChar('0'));

                fni = fni->NextEntryOffset?((FILE_NOTIFY_INFORMATION*)((char*)fni+fni->NextEntryOffset)):0;
            }

        } else {
            qCritical() << "ReadDirectoryChangeW failed: " << GetLastError();
        }

        QTimer::singleShot(0, this, SLOT(watchDir()));
    }
}
